package com.dhsc.util;

import com.dhsc.domain.yypt.LayuiTableVo;
import com.dhsc.domain.yypt.ResponseObject;
import com.dhsc.domain.yypt.yhzx.TYhxxVo;
import com.dhsc.exception.MyException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @ClassName:  CommonUtil
 * @Description: 公共方法类
 * @date:   2023年5月25日 下午6:33:15       
 * @author: clong
 * @Copyright:  东海运营
 */
@Slf4j
public class CommonUtil
{
	private static final ObjectMapper mapper = new ObjectMapper();
	//yyyyMMdd格式  
	private static final String YYYYMMDD = "yyyyMMdd";
	//yyyyMMdd格式  
	private static final String YYYYMM = "yyyyMM";
	//HH:mm:ss 格式 
	private static final String HHMMSS = "HH:mm:ss";
	//HHmmss 格式 
	private static final String HHMMSS1 = "HHmmss";
	//yyyy-MM-dd HH:mm:ss 格式  
	private static final String YYYY_MM_DDHHMMSS = "yyyy-MM-dd HH:mm:ss";
	//yyyyMMddHHmmss 格式  
	private static final String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
	//yyyy-MM-dd 格式  
	private static final String YYYY_MM_DD = "yyyy-MM-dd";
	//yyyyMMddHHmmssSSSS格式
	public static final String DEFAULT_TIME_MILL = "yyyyMMddHHmmssSSSS";
	//yyyy格式  
	private static final String YYYY = "yyyy";//yyyy格式  
	//mm格式  
	private static final String MM = "MM";
	//dd格式  
	private static final String DD = "dd";
	
	public static final String SQLJB = "存在SQL注入脚本！";

	// 定义不同图片格式的魔数头
	private static final byte[][] MAGIC_NUMBERS = {
			{(byte) 0xFF, (byte) 0xD8, (byte) 0xFF}, // JPEG
			{(byte) 0x89, 0x50, 0x4E, 0x47},        // PNG
			{0x47, 0x49, 0x46, 0x38},               // GIF
			{(byte) 0x42, (byte) 0x4D},             // BMP
			{(byte) 0x49, (byte) 0x49, (byte) 0x2A, (byte) 0x00}, // TIFF (Intel)
			{(byte) 0x4D, (byte) 0x4D, (byte) 0x00, (byte) 0x2A}  // TIFF (Motorola)
	};
	
	private CommonUtil()
	{

	}

	/**
	 * @Description:生成13位的随机数
	 * @return: long
	 * @Author: CDW
	 * @Date: 2023/11/16 15:38
	 */
	public static long generateRandom13Digit(SecureRandom secureRandom) {
		// 生成一个介于0和9999999999999之间的长整数
		long random13Digit = secureRandom.nextLong() % 10000000000000L;
		// 可能为负数，转为正数
		if (random13Digit < 0) {
			random13Digit = -random13Digit;
		}
		return random13Digit;
	}

	/**
	 * @Description:千位分隔符
	 * @return: java.lang.String
	 * @Author: CDW
	 * @Date: 2023/10/12 16:02
	 * @param o:
	 */
	public static String formatWithCommas(Object o) {
		double v = Double.parseDouble(o.toString());
		return String.format("%,.2f", v);
	}

	/**
	 * getDayBefore 获取当前日期的前一天日期
	 * @return
	 * String
	 * 朱晨晨 - zhuchenchen@sys-test.com.cn
	 * 2018年8月1日-下午3:17:53
	 */
	public static String getDayBefore(){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(new Date());
		calendar.add(Calendar.DAY_OF_MONTH, -1);
		return new SimpleDateFormat(YYYYMMDD).format(calendar.getTime());
	}

	/**
	 * @Description:
	 * @return: java.lang.String
	 * @Author: CDW
	 * @Date: 2023/8/1 15:05

	 */
	public static String printLine(){
		StackTraceElement[] trace = new Throwable().getStackTrace();
		// 下标为0的元素是上一行语句的信息, 下标为1的才是调用printLine的地方的信息
		StackTraceElement tmp = trace[1];
		return tmp.getClassName() + "." + tmp.getMethodName()
				+ "(" + tmp.getFileName() + ":" + tmp.getLineNumber() + ")"+tmp.toString();
	}


	/**
	 * @Title: getTimeMill
	 * @Description: yyyyMMddHHmmssSSSS格式
	 * @return String
	 * @author: chenlin
	 * @date:   2020年9月25日 下午5:19:32
	 */
	public static String getTimeMill(){
		SimpleDateFormat df=new SimpleDateFormat(DEFAULT_TIME_MILL);
		return df.format(new Date());
	}

	/**
	 * methodParameterType 获取方法对应的参数类型
	 * @return
	 * String
	 * 朱晨晨 - zhuchenchen@sys-test.com.cn
	 * 2018年3月12日-上午10:09:18
	 * @throws ClassNotFoundException
	 */
	public static Class<?>[] methodParameterType(Class<?> cl,String methodName) throws ClassNotFoundException{
		Class<?>[] cargs  = null;
		Method[] methods = cl.getDeclaredMethods();
		for (int i = 0; i < methods.length; i++) {
			Method method = methods[i];
			if (methodName.equals(method.getName())) {
				Class<?>[] paramsClass = method.getParameterTypes();//取得参数列表的所有类
				cargs = new Class<?>[paramsClass.length];
				int index=0;
				for (Class<?> class1 : paramsClass) {
					Class<?> forName = Class.forName(class1.getName());
					cargs[index]  = forName;
					index++;
				}
			}
		}
		return cargs;
	}

	/**
	 * subBetween 截取指定字符中间的值
	 * @param str
	 * @return
	 * String
	 * 朱晨晨 - zhuchenchen@sys-test.com.cn
	 * 2018年6月20日-下午4:31:30
	 */
	public static String subBetween(String str){
		if (CommonUtil.isNotEmptyObj(str)) {
			str = StringUtils.substringBetween(str,"(",")");
		}

		return str;
	}

	/**
	 * @Title: isEmpty
	 * @Description: 判断Collection及其子类是否为空，true为空
	 * @param c
	 * @return boolean
	 * @author: clong
	 * @date:   2023年5月25日 下午6:34:03
	 */
	public static boolean isEmptyCollection(Collection<?> c)
	{
		boolean result = true;
		if (null != c && !c.isEmpty())
		{
			result = false;
		}
		return result;
	}

	/**
	 * @Title: isEmpty
	 * @Description: 判断map及其子类是否为空
	 * @param map
	 * @return boolean
	 * @author: clong
	 * @date:   2023年5月25日 下午6:34:12
	 */
	public static boolean isEmptyMap(Map<?, ?> map)
	{
		boolean result = true;
		if (null != map && !map.isEmpty())
		{
			result = false;
		}
		return result;
	}
	
	/**
	 * @Title: isNotEmptyFile   
	 * @Description: 判断文件夹是否为空
	 * @param files
	 * @return boolean
	 * @author: clong
	 * @date:   2024年6月14日 上午9:42:08
	 */
	public static boolean isNotEmptyFile(File[] files)
	{
		return null != files && files.length > 0;
	}
	
	/**
	 * @Title: isNotEmpty
	 * @Description: 判断对象是否为空
	 * @param obj
	 * @return boolean
	 * @author: clong
	 * @date:   2023年5月25日 下午6:40:23
	 */
	public static boolean isNotEmptyObj(Object obj)
	{
		return null != obj && "null" != obj && obj != "" && !"".equals(obj) && !"[]".equals(obj);
	}

	/**
	 * @Title: isNotEmpty
	 * @Description: 判断集合收否为空
	 * @param list
	 * @return boolean
	 * @author: clong
	 * @date:   2023年5月25日 下午6:39:34
	 */
	public static boolean isNotEmptyList(@SuppressWarnings("rawtypes") List list)
	{
		return null != list && !list.isEmpty() && list.size() > 0;
	}
	
	public static boolean isNotEmptyBuilder(StringBuilder sb)
	{
		return sb.length() > 0;
	}

	/**
	 * @Title: getDate
	 * @Description: 获取系统当前时间 格式 :yyyy-MM-dd
	 * @return String
	 * @author: clong
	 * @date:   2023年5月25日 下午6:40:59
	 */
	public static String getDate()
	{
		//格式化日期
		SimpleDateFormat df = new SimpleDateFormat(YYYY_MM_DD);
		return df.format(new Date());
	}

	/**
	 * @Title: getTime
	 * @Description: 获取系统当前时间 格式 :HH:mm:ss
	 * @return String
	 * @author: clong
	 * @date:   2023年5月25日 下午6:41:10
	 */
	public static String getTime()
	{
		//格式化日期
		SimpleDateFormat df = new SimpleDateFormat(HHMMSS);
		return df.format(new Date());
	}
	
	public static String getTime1()
	{
		//格式化日期
		SimpleDateFormat df = new SimpleDateFormat(HHMMSS1);
		return df.format(new Date());
	}

	/**
	 * @Title: getDateTime
	 * @Description: 获取系统当前时间 格式 :yyyy-MM-dd HH:mm:ss
	 * @return String
	 * @author: clong
	 * @date:   2023年5月25日 下午6:41:18
	 */
	public static String getDateTime()
	{
		//格式化日期
		SimpleDateFormat df = new SimpleDateFormat(YYYY_MM_DDHHMMSS);
		return df.format(new Date());
	}

	/**
	 * @Title: getDateSystem
	 * @Description: 获取系统当前时间 格式 :yyyyMMdd
	 * @return String
	 * @author: clong
	 * @date:   2023年5月25日 下午6:41:24
	 */
	public static String getDateSystem()
	{
		//格式化日期
		SimpleDateFormat df = new SimpleDateFormat(YYYYMMDD);
		return df.format(new Date());
	}
	
	/**
	 * @Title: getBeforeDateSystem   
	 * @Description: 获取系统前一日时间 格式 :yyyyMMdd
	 * @return String
	 * @author: clong
	 * @date:   2024年6月3日 上午10:53:26
	 */
	public static String getBeforeDateSystem()
	{
		Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, -1);
        SimpleDateFormat dateFormat = new SimpleDateFormat(YYYYMMDD);
        return  dateFormat.format(calendar.getTime());
	}
	
	/**
	 * @Title: getBeforeDateSystem   
	 * @Description: 获取系统前一日时间 格式 :yyyy-MM-dd
	 * @return String
	 * @author: clong
	 * @date:   2024年6月3日 上午10:53:26
	 */
	public static String getBeforeDateSystem1()
	{
		Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, -1);
        SimpleDateFormat dateFormat = new SimpleDateFormat(YYYY_MM_DD);
        return  dateFormat.format(calendar.getTime());
	}

	/**
	 * @Title: getSystemTime
	 * @Description: 获取系统当前时间 格式 :yyyyMMddHHmmss
	 * @return String
	 * @author: clong
	 * @date:   2023年5月25日 下午6:41:31
	 */
	public static String getSystemTime()
	{
		//格式化日期
		SimpleDateFormat df = new SimpleDateFormat(YYYYMMDDHHMMSS);
		return df.format(new Date());
	}

	/**
	 * @Title: getSystemYyyyMm
	 * @Description: 获取系统当前时间 格式 :yyyyMM
	 * @return String
	 * @author: clong
	 * @date:   2023年9月21日 上午10:43:18
	 */
	public static String getSystemYyyyMm()
	{
		//格式化日期
		SimpleDateFormat df = new SimpleDateFormat(YYYYMM);
		return df.format(new Date());
	}
	/**
	 * 
	 * @Title: getSystemYyyy   
	 * @Description: 获取系统当前格式年份：yyyy
	 * @return String
	 * @author: shaozk
	 * @date:   2024年8月13日 下午3:17:55
	 */
	public static String getSystemYyyy()
	{
		SimpleDateFormat df = new SimpleDateFormat(YYYY);
		return df.format(new Date());
	}
		/**
	 * 
	 * @Title: getSystemMM   
	 * @Description: 获取系统当前格式月份：MM
	 * @return String
	 * @author: shaozk
	 * @date:   2024年8月13日 下午3:18:52
	 */
	public static String getSystemMM()
	{
		SimpleDateFormat df = new SimpleDateFormat(MM);
		return df.format(new Date());
	}
		/**
	 * 
	 * @Title: getSystemDD   
	 * @Description: 获取系统当前格式日期：DD
	 * @return String
	 * @author: shaozk
	 * @date:   2024年8月13日 下午3:23:06
	 */
	public static String getSystemDD()
	{
		SimpleDateFormat df = new SimpleDateFormat(DD);
		return df.format(new Date());
	}
	
	/**
	 * @Title: weakPassword
	 * @Description: 判断密码是否是弱密码  规则：以大小写字母开头，必须包含数字，可包含特殊字符（~!@&%$^\\(\\)#_），长度为8~20
	 * @param pwd
	 * @return boolean
	 * @author: clong
	 * @date:   2023年5月25日 下午6:41:47
	 */
	public static boolean weakPassword(String pwd)
	{
		Pattern p = Pattern.compile("^(?=.*[a-zA-Z])(?=.*[0-9])(?!.*([~!@&%$^\\(\\)#_]).*\\1.*\\1)[a-zA-Z0-9~!@&%$^\\(\\)#_]{8,20}$");
		Matcher m = p.matcher(pwd);
		return m.matches();
	}

	/**
	 * @Description: 对整个对象进行sql注入验证  包含-(目前都不含+-号)
	 * @MessageName:checkObjSQLAndJb
	 * @Param: obj
	 * @return: boolean
	 * @Author: jwj
	 * @Date: 2024/1/30 17:46
	 */
	public static boolean checkObjSQLAndJb(Object obj){
		// 获取对象的所有字段
		Field[] fields = obj.getClass().getDeclaredFields();

		for (Field field : fields) {
			// 设置字段可访问，即使是私有字段也可以获取其值
			field.setAccessible(true);
			try {
				// 检查字段的类型是否是String，如果是String类型，进行SQL注入验证
				if (field.getType().equals(String.class)) {
					// 获取字段的值
					Object value = field.get(obj);
					if (value!=null) {
						boolean flag=regSqlAndJbdh(value.toString());
						//如果含SQL脚本，则直接返回
						if(flag){
							return flag;
						}
					}
					// 如果非空，继续检查下一个属性
				}
				// 如果不是String类型，继续检查下一个属性
			} catch (IllegalAccessException e) {
				log.error("公共方法对整个对象进行sql注入验证异常", e);  
			}
		}
		return false;
	}

	/**
	* @Description: 对整个对象进行sql注入验证  (目前不含+、-、chr)
	* @MessageName: checkObjSQLAndJb
	* @param: obj
	* @return: boolean
	* @Author: gx
	* @Date: 2025/2/27 17:07
	*/
	public static boolean checkObjSQLAndJbNoChr(Object obj){
		// 获取对象的所有字段
		Field[] fields = obj.getClass().getDeclaredFields();

		for (Field field : fields) {
			// 设置字段可访问，即使是私有字段也可以获取其值
			field.setAccessible(true);
			try {
				// 检查字段的类型是否是String，如果是String类型，进行SQL注入验证
				if (field.getType().equals(String.class)) {
					// 获取字段的值
					Object value = field.get(obj);
					if (value!=null) {
						boolean flag=regSqlAndJbdhNoChr(value.toString());
						//如果含SQL脚本，则直接返回
						if(flag){
							return flag;
						}
					}
					// 如果非空，继续检查下一个属性
				}
				// 如果不是String类型，继续检查下一个属性
			} catch (IllegalAccessException e) {
				log.error("公共方法对整个对象进行sql注入验证异常", e);
			}
		}
		return false;
	}

	/**
	* @Description: 对整个对象进行sql注入验证
	* @MessageName: checkObjSQL
	* @param: obj
	* @return: boolean
	* @Author: gx
	* @Date: 2025/2/27 10:08
	*/
	public static boolean checkObjSQL(Object obj){
		// 获取对象的所有字段
		Field[] fields = obj.getClass().getDeclaredFields();

		for (Field field : fields) {
			// 设置字段可访问，即使是私有字段也可以获取其值
			field.setAccessible(true);
			try {
				// 检查字段的类型是否是String，如果是String类型，进行SQL注入验证
				if (field.getType().equals(String.class)) {
					// 获取字段的值
					Object value = field.get(obj);
					if (value!=null) {
						boolean flag=regSql(value.toString());
						//如果含SQL脚本，则直接返回
						if(flag){
							return flag;
						}
					}
					// 如果非空，继续检查下一个属性
				}
				// 如果不是String类型，继续检查下一个属性
			} catch (IllegalAccessException e) {
				log.error("公共方法对整个对象进行sql注入验证异常", e);
			}
		}
		return false;
	}

	/**
	 * @Title: regSqlAndJbdh
	 * @Description: sql注入验证  不包含- + ;
	 * @param str
	 * @return boolean
	 * @author: clong
	 * @date:   2023年5月25日 下午6:46:35
	 */
	public static boolean regSqlAndJbdh(String str)
	{
		if(CommonUtil.isNotEmptyObj(str))
		{
			Pattern pattern= Pattern.compile("\\b(and|exec|insert|select|drop|grant|alter|delete|update|count|chr|mid|master|truncate|char|declare|or)\\b|(')");
			Matcher matcher=pattern.matcher(str.toLowerCase());
			return matcher.find();
		}else{
			return false;
		}
	}

	/**
	* @Description: sql注入验证  不包含- + ; chr
	* @MessageName: regSqlAndJbdhNoChr
	* @param: str
	* @return: boolean
	* @Author: gx
	* @Date: 2025/2/27 17:06
	*/
	public static boolean regSqlAndJbdhNoChr(String str)
	{
		if(CommonUtil.isNotEmptyObj(str))
		{
			Pattern pattern= Pattern.compile("\\b(and|exec|insert|select|drop|grant|alter|delete|update|count|mid|master|truncate|char|declare|or)\\b|(')");
			Matcher matcher=pattern.matcher(str.toLowerCase());
			return matcher.find();
		}else{
			return false;
		}
	}

	/**
	* @Description: sql注入验证  不包含- + ; ''
	* @MessageName: regSql
	* @param: str
	* @return: boolean
	* @Author: gx
	* @Date: 2025/2/27 17:06
	*/
	public static boolean regSql(String str)
	{
		if(CommonUtil.isNotEmptyObj(str))
		{
			Pattern pattern= Pattern.compile("\\b(and|exec|insert|select|drop|grant|alter|delete|update|count|chr|mid|master|truncate|char|declare|or)\\b");
			Matcher matcher=pattern.matcher(str.toLowerCase());
			return matcher.find();
		}else{
			return false;
		}
	}

	/**
	 * @Title: safeString
	 * @Description: null转空字符串
	 * @param value
	 * @return String
	 * @author: clong
	 * @date:   2023年5月25日 下午9:44:24
	 */
	public static String safeString(Object value)
	{
		return null == value ? "" : value.toString();
	}

	/**
	 * @Title: getUUID
	 * @Description: 获取长度为32位的uuid
	 * @return String
	 * @author: clong
	 * @date:   2023年5月26日 上午9:14:46
	 */
	public static String getUUID()
	{
		String uuid = UUID.randomUUID().toString();
		return uuid.replace("-", "");
	}

	/**
	 * @Title: encodePassword
	 * @Description: 用户密码加密
	 * @param psw
	 * @return String
	 * @author: clong
	 * @date:   2023年5月29日 下午4:19:01
	 */
	public static String encodePassword(String psw) {
		if(StringUtils.isEmpty(psw)){
			return null;
		}else{
			return DigestUtils.sha1Hex(psw);
		}
	}

	/**
	 * @Title: matches
	 * @Description: 正则校验字符串
	 * @param regexp  正则表达式
	 * @param val   目标字符串
	 * @return boolean
	 * @author: clong
	 * @date:   2023年5月29日 下午4:19:20
	 */
	public static boolean matches(String regexp,String val)
	{
		Pattern p=Pattern.compile(regexp);
		Matcher matcher=p.matcher(val);
		return matcher.matches();
	}

	/**
	 * @Title: getUserVoInfoFromSession
	 * @Description: 从session中获取登录用户信息对象
	 * @param request
	 * @return
	 * @throws IOException TYhxxVo
	 * @author: clong
	 * @date:   2023年5月29日 下午4:58:48
	 */
	public static TYhxxVo getUserVoInfoFromSession(HttpServletRequest request)
	{
		HttpSession session = request.getSession();
		return (TYhxxVo) session.getAttribute("yhxx");
	}

	/**
	 * @Title: getCode
	 * @Description: 字符串数字+1
	 * @param originalValue
	 * @param identifier
	 * @return String
	 * @author: clong
	 * @date:   2023年5月31日 下午8:43:16
	 */
	public static String getCode(String originalValue, String identifier){
		if (!originalValue.contains(identifier)) {
			throw new MyException("original value does not contains identifier");
		}
		String num = originalValue.substring(identifier.length());
		int n = num.length();
		if ("".equals(num)) {
			num = "0";
		}
		int nums = Integer.parseInt(num) + 1;
		String newNum = String.valueOf(nums);
		n = Math.min(n, newNum.length());
		return originalValue.subSequence(0, originalValue.length() - n) + newNum;

	}

	/**
	 * @Title: getIpAddress
	 * @Description: 获取系统IP
	 * @param request
	 * @return String
	 * @author: clong
	 * @date:   2023年6月26日 下午2:42:53
	 */
	public static String getIpAddress(HttpServletRequest request) {
		 String remoteAddr = "";
		 if (request != null) {
			 remoteAddr = request.getHeader("X-FORWARDED-FOR");
            if (remoteAddr == null || "".equals(remoteAddr)) {
                remoteAddr = request.getRemoteAddr();
            }
        }
        return remoteAddr;
	}

	/**
	 * @Title: convert2String
	 * @Description: 将长整型数字转换为日期格式的字符串
	 * @param time
	 * @return String
	 * @author: chenlong
	 * @date:   2020年12月24日 下午5:11:30
	 */
	public static String convert2String(long time)
	{
		if (time > 0l)
		{
			SimpleDateFormat sf = new SimpleDateFormat(YYYY_MM_DDHHMMSS);
			Date date = new Date(time);
			return sf.format(date);
		}
		return "";
	}

	/**
	 * @Title: postobj
	 * @Description: http post
	 * @param o
	 * @param url
	 * @return
	 * @throws Exception ResponseObject
	 * @author: clong
	 * @throws IOException 
	 * @date:   2023年6月29日 下午7:34:48
	 */
	public static ResponseObject postobj(Object o, String url) throws IOException
	{
		String info = HttpClientUtil.postRequest(url, o);
		return JsonUtil.readValue(info, ResponseObject.class);
	}

	/**
	 * @Title: postLayuiobj
	 * @Description: http post 返回LayuiTableVo
	 * @param o
	 * @param url
	 * @return
	 * @throws Exception LayuiTableVo
	 * @author: clong
	 * @date:   2023年7月19日 下午1:37:10
	 */
	public static LayuiTableVo  postLayuiobj(Object o, String url) throws IOException
	{
		String info = HttpClientUtil.postRequest(url, o);
		return JsonUtil.readValue(info, LayuiTableVo.class);
	}

	/**
	* @Description: http post 钉钉运营
	* @MessageName: postDdyyobj
	* @param: o
    * @param: url
	* @return: ResponseObject
	* @Author: gx
	* @Date: 2025/4/8 11:26
	*/
	public static ResponseObject postDdyyobj(Object o, String url) throws IOException
	{
		String info = HttpClientUtil.postRequest(url, o);
		return JsonUtil.readValueIgnoreUnknown(info, ResponseObject.class);
	}

	/**
	 * @Title: noNullStringAttr
	 * @Description: 对象中null转“”
	 * @param cls
	 * @return T
	 * @author: clong
	 * @date:   2023年10月24日 下午7:42:58
	 */
	public static <T> T noNullStringAttr(T cls) {
		Field[] fields = cls.getClass().getDeclaredFields();
		if (fields == null || fields.length == 0) {
			return cls;
		}
		for (Field field : fields) {
			if (field.getType().getSimpleName() instanceof String) {
				field.setAccessible(true);
				try {
					Object value = field.get(cls);
					if (value == null) {
						field.set(cls, "");
					}
				} catch (IllegalArgumentException | IllegalAccessException e) {
					log.error("公共方法对象中null转“”异常", e);  
				}
			}
		}
		return cls;
	}

	/**
	 * @Title: readValueAsListIgnoreUnknown
	 * @Description: 忽略多余字段转list
	 * @param jsonStr
	 * @param c
	 * @return
	 * @throws IOException List<T>
	 * @author: chenlong
	 * @date:   2021年5月26日 下午5:15:35
	 */
	public static <T> List<T> readValueAsListIgnoreUnknown(String jsonStr,Class<T> c) throws IOException
	{
		if (null != jsonStr && !"".equals(jsonStr.trim()))
		{
			mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
			JavaType javaType = mapper.getTypeFactory().constructParametricType(List.class, c);
			return mapper.readValue(jsonStr, javaType);
		}
		return new ArrayList<>();
	}

	/**
	 * @Description:double 转 BigDecimal
	 * @return: java.math.BigDecimal
	 * @Author: CDW
	 * @Date: 2023/9/11 10:49
	 * @param val:
	 */
	public static BigDecimal convert(Object val)
	{
		return BigDecimal.valueOf(Double.parseDouble(val.toString())).setScale(2,BigDecimal.ROUND_HALF_UP);
	}

	/**
	 * szgsh  数值格式化
	 * @param val
	 * @return
	 * Double
	 * 朱晨晨 - zhuchenchen@sys-test.com.cn
	 * 2018年9月19日-下午1:20:38
	 */
	public static Double szgsh(Double val){
		BigDecimal bg = BigDecimal.valueOf(val);
		val = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
		return val;
	}

	/**
	 * @Title: compTime
	 * @Description: 比较两个时间 时分秒 大小
	 * @param s1
	 * @param s2
	 * @return boolean
	 * @author: chenlong
	 * @date:   2021年12月5日 下午2:46:27
	 */
	public static boolean compTime(String s1,String s2){
		String[]array1 = s1.split(":");
		int total1 = Integer.valueOf(array1[0])*3600+Integer.valueOf(array1[1])*60+Integer.valueOf(array1[2]);
		String[]array2 = s2.split(":");
		int total2 = Integer.valueOf(array2[0])*3600+Integer.valueOf(array2[1])*60+Integer.valueOf(array2[2]);
		return total1-total2 >= 0;
	}

	//根据当前日期查询周一周五所在日期
	public static String dateWeek(Date d) {
		Calendar c = Calendar.getInstance();
		// 设置每周的开始日期
		c.setFirstDayOfWeek(Calendar.MONDAY);
		c.setTime(d);
		c.setMinimalDaysInFirstWeek(7);
	    
		int year=c.get(Calendar.YEAR);
		int weeks=c.get(Calendar.WEEK_OF_YEAR);
		//判断周数如果为52，月份不为12月，则代表跨年周，所属年份需减一
		if(c.get(Calendar.WEEK_OF_YEAR) == 52 && (c.get(Calendar.MONTH) + 1) < 12){
			year=c.get(Calendar.YEAR) -1;
		}
		SimpleDateFormat sdf=new SimpleDateFormat(YYYY_MM_DD);
		Calendar cal=Calendar.getInstance();
		// 设置每周的开始日期
		cal.setFirstDayOfWeek(Calendar.MONDAY);
		cal.setMinimalDaysInFirstWeek(7);
		cal.set(Calendar.YEAR, year);
		cal.set(Calendar.WEEK_OF_YEAR, weeks);
		cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek());
		String beginDate = sdf.format(cal.getTime());

		cal.add(Calendar.DAY_OF_WEEK, 6);
		String endDate = sdf.format(cal.getTime());
		return beginDate+"&&"+endDate;
	}

	public static Date transition(String str) throws ParseException {
		SimpleDateFormat formatter = new SimpleDateFormat(YYYYMMDD);
		return formatter.parse(str);
	}

	/**
	 *
	 * @Title: strAddZero
	 * @Description: 补零
	 * @param str
	 * @param lth
	 * @return String
	 * @author: cdw
	 * @date:   2022年9月23日 下午2:25:34
	 */
	public static String strAddZero(String str,int lth){
		String  strAddZero = str + "" ;
		//判断字符串长度为1时,在改字符串前面补零
		for(int a =lth; a < 4;  a++){
			strAddZero = (strAddZero.length() < 1) ? strAddZero : 0 + strAddZero;
		}
		return strAddZero;
	}

	public static String replaceAll(String str) {
		if (null != str)
		{
			return str.trim();
		}
		return "";
	}

	public static int getXssfVaildRows(Sheet sheet){
		CellReference cellReference = new CellReference("A1");
		boolean flag = false;
		for (int i = cellReference.getRow(); i <= sheet.getLastRowNum(); ) {
			Row r = sheet.getRow(i);

			if (r == null) {
				// 如果是空行(即没有任何数据、格式)，直接把它以下的数据往上移动
				if(i + 1<sheet.getLastRowNum()){
					sheet.shiftRows(i + 1, sheet.getLastRowNum(), -1);
					continue;
				}else{
					return sheet.getLastRowNum() + 1;

				}
			}
			int a = 0;
			flag = false;
			for (Cell c : r) {
				//将数字格式的单元格转换成文本格式
				XSSFCell content = (XSSFCell) r.getCell(a);
				a++;
				if(CommonUtil.isNotEmptyObj(content)){
					content.setCellType(Cell.CELL_TYPE_STRING);
					if (r.getCell((short) a-1) != null) {
						if ((r != null) && (c.toString() != null)  &&
								(c.getCellType()!=Cell.CELL_TYPE_BLANK) && !(r.getCell((short) a-1).getStringCellValue().trim()).equals("")) {
							flag = true;
							break;
						}
					}else{
						if ((r != null) && (c.toString() != null)  &&
								(c.getCellType()!=Cell.CELL_TYPE_BLANK)) {
							flag = true;
							break;
						}
					}
				}

			}
			if (flag)
			{
				i++;
			} else {
				//如果是空白行(即可能没有数据，但是有一定格式)
				if (i == sheet.getLastRowNum())
					//如果到了最后一行，直接将那一行remove掉
					sheet.removeRow(r);
				else//如果还没到最后一行，则数据往上移一行
					sheet.shiftRows(i + 1, sheet.getLastRowNum(), -1);
			}
		}

		return sheet.getLastRowNum() + 1;
	}
	/**
	 *
	 * @Title: getVaildRows
	 * @Description: 对导入的无效行数做判断
	 * @param sheet
	 * @return int
	 * @author: caodw
	 * @date:   2021年8月17日 上午11:23:25
	 */
	public static int getVaildRows(Sheet sheet){
		CellReference cellReference = new CellReference("A1");
		boolean flag = false;
		for (int i = cellReference.getRow(); i <= sheet.getLastRowNum(); ) {
			Row r = sheet.getRow(i);

			if (r == null) {
				// 如果是空行(即没有任何数据、格式)，直接把它以下的数据往上移动
				if(i + 1<sheet.getLastRowNum()){
					sheet.shiftRows(i + 1, sheet.getLastRowNum(), -1);
					continue;
				}else{
					return sheet.getLastRowNum() + 1;

				}
			}
			int a = 0;
			flag = false;
			for (Cell c : r) {
				//将数字格式的单元格转换成文本格式
				HSSFCell content = (HSSFCell) r.getCell(a);
				a++;
				if(CommonUtil.isNotEmptyObj(content)){
					content.setCellType(Cell.CELL_TYPE_STRING);
					if (r.getCell((short) a-1) != null) {
						if ((r != null) && (c.toString() != null)  &&
								(c.getCellType()!=Cell.CELL_TYPE_BLANK) && !(r.getCell((short) a-1).getStringCellValue().trim()).equals("")) {
							flag = true;
							break;
						}
					}else{
						if ((r != null) && (c.toString() != null)  &&
								(c.getCellType()!=Cell.CELL_TYPE_BLANK)) {
							flag = true;
							break;
						}
					}
				}

			}
			if (flag)
			{
				i++;
			} else {
				//如果是空白行(即可能没有数据，但是有一定格式)
				if (i == sheet.getLastRowNum())
					//如果到了最后一行，直接将那一行remove掉
					sheet.removeRow(r);
				else//如果还没到最后一行，则数据往上移一行
					sheet.shiftRows(i + 1, sheet.getLastRowNum(), -1);
			}
		}

		return sheet.getLastRowNum() + 1;
	}

	//日期格式规范校验
	public static boolean isDate(String strDate) {
		String reg = "^((\\d{2}(([02468][048])|([13579][26]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))(\\s(((0?[0-9])|([1-2][0-3]))\\:([0-5]?[0-9])((\\s)|(\\:([0-5]?[0-9])))))?$";
		Pattern pattern = Pattern.compile(reg);
		Matcher matcher = pattern.matcher(strDate);
		boolean result = false;
		if (matcher.matches()) {
			result = true;
		}
		return result;
	}

	//判断字符串不能以0为开头并且长度为6
	public static boolean isNumeric(String str){
		boolean result = false;
		if(CommonUtil.isNotEmptyObj(str.trim()) && Pattern.compile("^[1-9]\\d*$").matcher(str).matches() && str.length() ==8){
			result = true;
		}
		return result;
	}

	//折算系数规范校验
	public static boolean checkAmount(String str) {
		boolean result = false;
		if(CommonUtil.isNotEmptyObj(str.trim()))
		{
			return result;
		}
		Pattern pattern = Pattern.compile("^(([1-9]\\d*)|\\d)(\\.\\d{1,2})?$");
		Matcher matcher = pattern.matcher(str);
		if(matcher.matches()){
			result = true;
		}
		return result;
	}

	/**
	 * @Title: getFileNameByPath
	 * @Description: 根据路径获取文件名
	 * @param path
	 * @param needSuffix
	 * @return String
	 * @author: clong
	 * @date:   2023年9月20日 下午1:29:13
	 */
	public static String getFileNameByPath(String path, boolean needSuffix)
	{
		StringBuilder regExp = new StringBuilder();
		regExp.append("([^<>/\\\\|:\"\"\\*\\?]+)");
		if (!needSuffix)
		{
			regExp.append("\\.\\w+");
		}
		regExp.append("$");
		Pattern p = Pattern.compile(regExp.toString());
		Matcher m = p.matcher(path);
		if (!m.find())
		{
			return "";
		}
		return m.group(1);
	}

	/**
	 * @Title: getHssfCell
	 * @Description: 赋予HSSF样式
	 * @Param: sheet
	 * @Param: style
	 * @Param: row
	 * @Param: column
	 * @Param: width
	 * @return: HSSFCell
	 * @Author: gx
	 * @Date: 2023/10/24 15:49
	 */
	public static HSSFCell getHssfCell(HSSFSheet sheet, HSSFCellStyle style, HSSFRow row, int column, int width) {
		HSSFCell cell = row.createCell(column);
		cell.setCellStyle(style);
		sheet.setColumnWidth(column, width);
		return cell;
	}

	/**
	 * @Title: getXssfCell
	 * @Description: 赋予XSSF样式
	 * @Param: sheet
	 * @Param: style
	 * @Param: row
	 * @Param: column
	 * @Param: width
	 * @return: XSSFCell
	 * @Author: gx
	 * @Date: 2023/10/24 15:49
	 */
	public static XSSFCell getXssfCell(XSSFSheet sheet, XSSFCellStyle style, XSSFRow row, int column, int width) {
		XSSFCell cell = row.createCell(column);
		cell.setCellStyle(style);
		sheet.setColumnWidth(column, width);
		return cell;
	}

	/**
	 * @Title: isEffectiveDate
	 * @Description: 判断日期是否在某个范围内
	 * @param stime
	 * @param etime
	 * @param time
	 * @return
	 * @throws ParseException boolean
	 * @author: clong
	 * @date:   2023年11月14日 上午10:32:21
	 */
	public static boolean isEffectiveDate(String stime, String etime, String time) throws ParseException
	{
		boolean result = false;
		SimpleDateFormat ft = new SimpleDateFormat();
		ft.applyPattern(YYYY_MM_DD);
		Date startTime = ft.parse(stime.substring(0, 4) + "-" + stime.substring(4, 6) + "-" + stime.substring(6, 8));
		Date endTime = ft.parse(etime.substring(0, 4) + "-" + etime.substring(4, 6) + "-" + etime.substring(6, 8));
		Date nowTime = ft.parse(time.substring(0, 4) + "-" + time.substring(4, 6) + "-" + time.substring(6, 8));

		if (nowTime.getTime() == startTime.getTime() || nowTime.getTime() == endTime.getTime()) {
			result = true;
		}else{
			Calendar date = Calendar.getInstance();
			date.setTime(nowTime);

			Calendar begin = Calendar.getInstance();
			begin.setTime(startTime);

			Calendar end = Calendar.getInstance();
			end.setTime(endTime);

			if (date.after(begin) && date.before(end)) {
				result = true;
			} else {
				result = false;
			}
		}
		return result;
	}


	/**
	 * @Title: getAscDateList
	 * @Description: 获取 日期区间内 全部日期
	 * @param stime
	 * @param etime
	 * @return List<String>
	 * @author: clong
	 * @date:   2023年11月14日 上午10:38:32
	 */
	public static List<String> getAscDateList(String stime, String etime) {
		LocalDate startDate = LocalDate.parse(stime);
		LocalDate endDate = LocalDate.parse(etime);

		List<String> result = new ArrayList<>();
		if (endDate.compareTo(startDate) < 0) {
			return result;
		}
		while (true) {
			result.add(startDate.toString());
			if (startDate.compareTo(endDate) >= 0) {
				break;
			}
			startDate = startDate.plusDays(1);
		}
		return result;
	}

	/**
	 * @Title: dateCompare
	 * @Description: 比较日期大小
	 * @param time1
	 * @param time2
	 * @return boolean
	 * @author: clong
	 * @throws ParseException
	 * @date:   2023年11月14日 下午1:09:56
	 */
	public static boolean dateCompare(String time1, String time2) throws ParseException{
		boolean result = false;
		SimpleDateFormat sdf = new SimpleDateFormat(YYYY_MM_DD);
		Date date1 = sdf.parse(time1.substring(0, 4) + "-" + time1.substring(4, 6) + "-" + time1.substring(6, 8));
		Date date2 = sdf.parse(time2);
		if (date1.compareTo(date2) > 0) {
			result = true;
		}
		return result;
	}

	/**
	 * @Title: datesOfWeek
	 * @Description: 获取本周所有日期
	 * @Title: datesOfWeek
	 * @Description: 获取一周所有日期
	 * @param type   0 本周    1.上一周   2、上两周  以此类推
	 * @return List<String>
	 * @author: clong
	 * @date:   2023年11月23日 下午8:06:07
	 */
	public static List<String> datesOfWeek(int type){
		// 获取当前日期
		LocalDate currentDate = LocalDate.now();
		//获取本周的第一天
		LocalDate firstDayOfWeek = currentDate.with(DayOfWeek.MONDAY);
		if(type != 0)
		{
			LocalDate lastMonday = firstDayOfWeek.minusDays(7L*type);

			// 获取本周的最后一天
			LocalDate lastDayOfWeek = lastMonday.plusDays(6);

			List<String> datesOfWeek = new ArrayList<>();
			for (LocalDate date = lastMonday; !date.isAfter(lastDayOfWeek); date = date.plusDays(1)) {
				String dateStr = date.format(DateTimeFormatter.ofPattern(YYYYMMDD));
				datesOfWeek.add(dateStr);
			}
			return datesOfWeek;
		}else{
			// 获取本周的最后一天
			LocalDate lastDayOfWeek = firstDayOfWeek.plusDays(6);

			List<String> datesOfWeek = new ArrayList<>();
			for (LocalDate date = firstDayOfWeek; !date.isAfter(lastDayOfWeek); date = date.plusDays(1)) {
				String dateStr = date.format(DateTimeFormatter.ofPattern(YYYYMMDD));
				datesOfWeek.add(dateStr);
			}
			return datesOfWeek;
		}
	}

	public static String getTransString(String s, List<String> jyr, String clrq) {

		// $rq-004$
		String result = s;
		while (result.indexOf("$rq") != -1) {
			String qz = result.substring(0, result.indexOf("$rq"));
			String hz = result.substring(result.indexOf("$rq") + 8);
			String zj = result.substring(result.indexOf("$rq"), result.indexOf("$rq") + 8);
			zj = getFormRq(jyr, zj, clrq);
			result = qz + zj + hz;
		}
		return result;
	}

	public static String getFormRq(List<String> jyr, String rq, String dt) {
		String result = "30000000";
		//$rq-001$
		if (rq.length() == 8) {
			String fh = rq.substring(3, 4);
			String nf = rq.substring(4, 5);
			String yf = rq.substring(5, 6);
			String rf = rq.substring(6, 7).toUpperCase();
			if (rf.equals("A")) {
				rf = "10";
			} else if (rf.equals("B")) {
				rf = "11";
			} else if (rf.equals("C")) {
				rf = "12";
			} else if (rf.equals("D")) {
				rf = "13";
			} else if (rf.equals("E")) {
				rf = "14";
			} else if (rf.equals("F")) {
				rf = "15";
			} else if (rf.equals("G")) {
				rf = "16";
			} else if (rf.equals("H")) {
				rf = "17";
			} else if (rf.equals("I")) {
				rf = "18";
			} else if (rf.equals("J")) {
				rf = "19";
			} else if (rf.equals("K")) {
				rf = "20";
			} else if (rf.equals("L")) {
				rf = "21";
			} else if (rf.equals("M")) {
				rf = "22";
			} else if (rf.equals("N")) {
				rf = "23";
			}
			if (fh.equals("-")) {
				if (Integer.parseInt(nf) > 0) {
					dt = (Integer.parseInt(dt.substring(0, 4)) - Integer.parseInt(nf)) + dt.substring(4);
				}
				int yfsl = Integer.parseInt(yf);
				while (yfsl > 0) {
					dt = getLastMonth(dt.substring(0, 6)) + dt.substring(6);
					yfsl--;
				}
				result = dt;
				int rfsl = Integer.parseInt(rf);
				if (rfsl > 0) {
					for (int i = 0; i < jyr.size(); i++) {
						if (Integer.parseInt(dt) > Integer.parseInt(jyr.get(i)) && rfsl > 0) {
							result = jyr.get(i);
							rfsl--;
						}
					}
				}
			} else if (fh.equals("+")) {
				if (Integer.parseInt(nf) > 0) {
					dt = (Integer.parseInt(dt.substring(0, 4)) + Integer.parseInt(nf)) + dt.substring(4);
				}
				int yfsl = Integer.parseInt(yf);
				while (yfsl > 0) {
					dt = getNextMonth(dt.substring(0, 6)) + dt.substring(6);
					yfsl--;
				}
				result = dt;
				int rfsl = Integer.parseInt(rf);
				if (rfsl > 0) {
					for (int i = 0; i < jyr.size(); i++) {
						if (Integer.parseInt(dt) < Integer.parseInt(jyr.get(jyr.size() - 1 - i)) && rfsl > 0) {
							result = jyr.get(jyr.size() - 1 - i);
							rfsl--;
						}
					}
				}
			}
		}
		return result;
	}

	public static String getLastMonth (String time) {
		if (time == null) {
			return null;
		}
		if (time.equals("")) {
			return "";
		}
		if (time.endsWith("O1")) {
			return (Integer.parseInt(time.substring(0, 4)) - 1) + "12";
		}
		if (time.endsWith("12")) {
			return (Integer.parseInt(time.substring(0, 4))) + "11";
		}
		if (time.endsWith("11")) {
			return (Integer.parseInt(time.substring(0, 4))) + "10";
		}
		if (time.endsWith("10")) {
			return (Integer.parseInt(time.substring(0, 4))) + "09";
		}
		return time.substring(0, 5) + (Integer.parseInt(time.substring(5)) - 1);
	}



	public static String getNextMonth (String time) {
		if (time == null) {
			return null;
		}
		if (time.equals("")) {
			return "";
		}
		if (time.endsWith("12")) {
			return (Integer.parseInt(time.substring(0, 4)) + 1) + "01";
		}
		if (time.endsWith("11")) {
			return (Integer.parseInt(time.substring(0, 4))) + "12";
		}
		if (time.endsWith("10")) {
			return (Integer.parseInt(time.substring(0, 4))) + "11";
		}
		if (time.endsWith("09")) {
			return (Integer.parseInt(time.substring(0, 4))) + "10";
		}
		return time.substring(0, 5) + (Integer.parseInt(time.substring(5)) + 1);
	}

	/**
	 * @Title: getLastMonthDay
	 * @Description: 获取上个月最后一天自然日
	 * @return String
	 * @author: clong
	 * @date:   2023年11月26日 下午12:10:52
	 */
	public static String getLastMonthDay() {
		Calendar calendar = Calendar.getInstance();
		int year = calendar.get(Calendar.YEAR);
		int month = calendar.get(Calendar.MONTH);
		int lastMonth;
		if (month == 0) {
			lastMonth = 11;
		}else{
			lastMonth = month - 1;
		}
		calendar.set(year, lastMonth, 1);
		calendar.add(Calendar.MONTH, 1);
		calendar.add(Calendar.DAY_OF_MONTH, -1);
		Date lastMonthEndDate = calendar.getTime();
		SimpleDateFormat dateFormat = new SimpleDateFormat(YYYYMMDD);
		return dateFormat.format(lastMonthEndDate);

	}

	/**
	 * @Title: encodeMd5
	 * @Description: md5加密
	 * @param pass
	 * @return
	 * @throws Exception String
	 * @author: clong
	 * @throws NoSuchAlgorithmException 
	 * @date:   2023年12月4日 上午10:24:20
	 */
	public static String encodeMd5(String pass) throws NoSuchAlgorithmException{
		MessageDigest md5 = MessageDigest.getInstance("MD5");

		byte[] byteArray = pass.getBytes(StandardCharsets.UTF_8);
		byte[] md5Bytes = md5.digest(byteArray);
		StringBuilder hexValue = new StringBuilder();
		for (int i = 0; i < md5Bytes.length; i++) {
			int val = (md5Bytes[i]) & 0xff;
			if (val < 16) {
				hexValue.append("0");
			}
			hexValue.append(Integer.toHexString(val));
		}
		return hexValue.toString();
	}

	/**
	 * @Title: checkPassGz
	 * @Description: 校验密码规则
	 * @return boolean
	 * @author: clong
	 * @date:   2023年12月4日 上午10:31:36
	 */
	public static boolean checkPassGz(String pass){
		String reg = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[!@#$%^&*.]).{12,20}$";
		return pass.matches(reg);
	}

	/**
	 * @Title: stringChangeJe
	 * @Description: 数字千分位分割
	 * @return String
	 * @author: clong
	 * @date:   2024年1月26日 上午10:52:45
	 */
	public static String stringChangeJe(String val)
	{
		double amount = Double.parseDouble(val);

		DecimalFormat decimalFormat = (DecimalFormat) NumberFormat.getCurrencyInstance();
		decimalFormat.applyPattern("###,###,###.###");
		return decimalFormat.format(amount);
	}
	
	/**
	 * @Title: xssEncode   
	 * @Description: 将容易引起xss漏洞的半角字符直接替换成全角字符
	 * @param s
	 * @return String
	 * @author: clong
	 * @date:   2024年3月20日 下午2:26:54
	 */
	public static String xssEncode(String s) {
		if (s == null || s.isEmpty()) {
			return s;
		}
		StringBuilder sb = new StringBuilder(s.length() + 16);
		for (int i = 0; i < s.length(); i++) {
			char c = s.charAt(i);
			switch (c) {
				case '>':
					sb.append('＞');//全角大于号
					break;
				case '<':
					sb.append('＜');//全角小于号
					break;
				case '\'':
					sb.append('‘');//全角单引号
					break;
				case '&':
					sb.append('＆');//全角
					break;
				case '#':
					sb.append('＃');//全角井号
					break;
				default:
					sb.append(c);
					break;
			}
		}
		return sb.toString();
	}

	public static String clhh(String val)
	{
		String value= "";
		if(CommonUtil.isNotEmptyObj(val)){
			if(val.indexOf("/n") != -1){
				value= val.replace("/n", "\n");
			}else{
				value= val;
			}
		}
		return value;
	}

	/**
	 * @Description:关键信息脱敏
	 * @return: java.lang.String
	 * @Author: CDW
	 * @Date: 2024/5/8 14:21
	 * @param obj:
	 */
    public static String gjxxtm(String obj) {
		if (CommonUtil.isNotEmptyObj(obj)) {
			String khxm = null;
					//个人
			if (obj.length() == 2) {
				khxm = obj.replaceFirst(obj.substring(1), "*");
				return khxm;
			}
			if (obj.length() > 2) {
				StringBuilder maskedNumber = new StringBuilder(obj.substring(0, 1));
				for (int i = 1; i < obj.length() -1; i++) {
					maskedNumber.append('*');
				}
				maskedNumber.append(obj.substring(obj.length() - 1));
				return maskedNumber.toString();
			}
		}
		return obj;
	}

	/**
	 * @Description: 比较相同实体字段值不相同的字段
	 * @MessageName: compareFields
	 * @param: obj1
    * @param: obj2
	 * @return: List<String>
	 * @Author: jwj
	 * @Date: 2024/5/23 11:17
	 */
	public static <T> List<String> compareFields(T obj1, T obj2) throws IllegalAccessException {
		List<String> differences = new ArrayList<>();

		if (obj1 == null || obj2 == null) {
			return differences;
		}

		Class<?> clazz = obj1.getClass();
		for (Field field : clazz.getDeclaredFields()) {
			field.setAccessible(true); // 如果字段不是public的，设置为可访问
			try {
				Object value1 = field.get(obj1);
				Object value2 = field.get(obj2);
				if (!Objects.equals(value1, value2)) {
					differences.add(field.getName());
				}
			} catch (IllegalArgumentException e) {
				// 处理可能的异常，比如字段类型不支持get方法
				log.error("公共方法比较相同实体字段值不相同的字段异常", e);  
			}
		}

		return differences;
	}

	//判断字节长度
	public static int getByteLength(String str) {
		if (str == null) {
			return 0;
		}
		try {
			// 使用UTF-8编码的getBytes()方法获取字节数组
			byte[] bytes = str.getBytes("UTF-8");
			// 返回字节数组的长度
			return bytes.length;
		} catch (UnsupportedEncodingException e) {
			// UTF-8是Java平台支持的字符编码，这里捕获异常主要是出于代码健壮性的考虑
			// 在实际使用中，这个异常几乎不会发生
			e.printStackTrace();
			return 0;
		}
	}
	
	/**
	 * @Title: transCxzzfw   
	 * @Description: 查询资质权限
	 * @param s
	 * @return String
	 * @author: clong
	 * @date:   2024年10月28日 上午10:08:35
	 */
	public static String transCxzzfw(String s)
	{
		String result = "基本交易权限;";
		if(!";".equals(s))
		{
			if(s.indexOf(";1;") != -1)
				result=result+"融资融券;";
			if(s.indexOf(";2;") != -1)
				result=result+"沪港通;";
			if(s.indexOf(";3;") != -1)
				result=result+"深港通;";
			if(s.indexOf(";4;") != -1)
				result=result+"股转交易;";
			if(s.indexOf(";5;") != -1)
				result=result+"股票期权;";
			if(s.indexOf(";6;") != -1)
				result=result+"债券合格投资者;";
			if(s.indexOf(";7;") != -1)
				result=result+"退市整理;";
			if(s.indexOf(";8;") != -1)
				result=result+"分级基金;";
			if(s.indexOf(";9;") != -1)
				result=result+"回购融资;";
			if(s.indexOf(";10;") != -1)
				result=result+"质押回购;";
			if(s.indexOf(";11;") != -1)
				result=result+"约定购回;";
			if(s.indexOf(";12;") != -1)
				result=result+"B类专业投资者;";
			if(s.indexOf(";13;") != -1)
				result=result+"C类专业投资者;";
			if(s.indexOf(";14;") !=- 1)
				result=result+"科创板;";
			if(s.indexOf(";15;") != -1)
				result=result+"创业板;";
			if(s.indexOf(";99;") != -1)
				result=result+"北交所;";
		}
		if(result.endsWith(";"))
		{
			result=result.substring(0, result.length()-1);
		}
		return result;
	}

	/**
	 * @Description: 查找图片文件头在字节数组中的起始位置
	 * @MessageName: findImageStart
	 * @param: data
	 * @return: int
	 * @Author: jwj
	 * @date: 2025/2/20 10:13
	 */
	public static int findImageStart(byte[] data) {
		for (int i = 0; i <= data.length - 3; i++) { // 从最小的魔数长度开始检查
			for (byte[] magicNumber : MAGIC_NUMBERS) {
				if (i <= data.length - magicNumber.length) {
					boolean found = true;
					for (int j = 0; j < magicNumber.length; j++) {
						if (data[i + j] != magicNumber[j]) {
							found = false;
							break;
						}
					}
					if (found) {
						return i;
					}
				}
			}
		}
		return -1; // 如果没有找到，则返回-1
	}
}
